import Mat from "./Mat";

export default class Vector extends Mat {
    constructor(data) {
        super([data])
    }

    sub (start, len) {
        return Vector.create(1, len, (i, j) => {
            return this.data.length > 1?this.data[j + start][i]:this.data[i][j + start]
        })
    }
    set_by_index (index, value) {
        let iv = this.data.length > 1
        for (let i of index) {
            iv?this.data[i][0] = value:this.data[0][i] = value
        }
    }
    set_from_range (indexes, values) {
        let iv = this.data.length > 1
        for (let i = 0;i < indexes.length; i++) {
            iv?this.data[indexes[i]][0] = values[i]:this.data[0][indexes[i]] = values[i]
        }
    }
    sum () {
        let result = 0
        for (let i in this.data) {
            for (let j in i) {
                result += j
            }
        }
        return result
    }

    sum_by_index (start, end) {
        let result = 0
        let iv = this.data.length > 1
        for (let i = start;i < end; i++) {
            result += iv?this.data[i][0]:this.data[0][i]
        }
        return result
    }
    cumsum () {
        let ret = [],
            iv = this.data.length > 1,
            len = iv?this.data.length:this.data[0].length
        ret[0] = this.data[0][0]
        for (let i = 1; i < len; i++) {
            ret[i] = ret[i - 1] + iv?this.data[i][0]:this.data[0][i]
        }
        return new Vector(ret)
    }
    where (fn) {
        let index = [], iv = this.data.length > 1
        let len = iv?this.data.length:this.data[0].length
        for (let i = 0; i < len;i++) {
            if (fn(iv?this.data[i][0]:this.data[0][i])) {
                index.push(i)
            }
        }
        return index
    }

    max () {
        let index = 0,max = this.data[0][0]
        let iv = this.data.length > 1
        let len = iv?this.data.length:this.data[0].length
        for (let i = 1; i < len; i++) {
            let item = iv?this.data[i][0]:this.data[0][i]
            if (item > max) {
                max = item
                index = i
            }
        }
        return { index,max }
    }
    min () {
        let index = 0,min = this.data[0][0]
        let iv = this.data.length > 1
        let len = iv?this.data.length:this.data[0].length
        for (let i = 1; i < len; i++) {
            let item = iv?this.data[i][0]:this.data[0][i]
            if (item < min) {
                min = item
                index = i
            }
        }
        return { index,min }
    }

    mean () {
        let sum = this.sum()
        let len = this.data.length > 1?this.data.length:this.data[0].length
        return sum/len
    }
    abs () {
        return Vector.create(this.rows, this.columns, (i, j) => {
            return Math.abs(this.data[i][j])
        })
    }
    sqrt () {
        return Vector.create(this.rows, this.columns, (i, j) => {
            return Math.sqrt(this.data[i][j])
        })
    }
    std () {
        let temp = Vector.__and__(this, this)
        let sum = temp.sum()
        let len = sum.rows > 1?sum.rows:sum.columns
        return Math.sqrt(sum/len)
    }
    static range (length) {
        return this.create(1,length, (i, j) => {
            return j
        })
    }
    static arange (start,length) {
        return this.create(1, length, (i, j) => {
            return start + j
        })
    }

    /**
     * 矩阵加法运算
     */
    static __add__(vect1, vect2) {
        if (vect1 instanceof Vector && /^[0-9]+[\.]?[0-9]?$/.test(vect2)) {
            return this.create(vect1.rows, vect1.columns, (i, j) => {
                return vect1.data[i][j] + vect2
            })
        } else if (/^[0-9]+[\.]?[0-9]?$/.test(vect1) && vect2 instanceof Vector) {
            return this.create(vect2.rows, vect2.columns, (i, j) => {
                return vect1 + vect2.data[i][j]
            })
        } else {
            super.__add__(vect1, vect2)
        }
    }

    /**
     * 矩阵减法运算
     */
    static __plus__(vect1, vect2) {
        if (vect1 instanceof Vector && /^[0-9]+[\.]?[0-9]?$/.test(vect2)) {
            return this.create(vect1.rows, vect1.columns, (i, j) => {
                return vect1.data[i][j] - vect2
            })
        } else if (/^[0-9]+[\.]?[0-9]?$/.test(vect1) && vect2 instanceof Vector) {
            return this.create(vect2.rows, vect2.columns, (i, j) => {
                return vect1 - vect2.data[i][j]
            })
        } else {
            super.__plus__(vect1, vect2)
        }
    }

    /**
     * 矩阵乘法运算
     */
    static __and__(vect1, vect2) {
        if (vect1 instanceof Vector && /^[0-9]+[\.]?[0-9]?$/.test(vect2)) {
            return this.create(vect1.rows, vect1.columns, (i, j) => {
                return vect1.data[i][j] * vect2
            })
        } else if (/^[0-9]+[\.]?[0-9]?$/.test(vect1) && vect2 instanceof Vector) {
            return this.create(vect2.rows, vect2.columns, (i, j) => {
                return vect1 * vect2.data[i][j]
            })
        } else {
            super.__and__(vect1, vect2)
        }
    }


    static __mod__(vect1, vect2) {
        if (vect1 instanceof Vector && /^[0-9]+[\.]?[0-9]?$/.test(vect2)) {
            return this.create(vect1.rows, vect1.columns, (i, j) => {
                return vect1.data[i][j] / vect2
            })
        } else if (/^[0-9]+[\.]?[0-9]?$/.test(vect1) && vect2 instanceof Vector) {
            return this.create(vect2.rows, vect2.columns, (i, j) => {
                return vect1 / vect2.data[i][j]
            })
        } else {
            super.__mod__(vect1, vect2)
        }
    }

}

